import random
from datetime import timedelta

from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import make_password
from django.contrib.sites.models import Site
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils import timezone

from uuslug import slugify

from blog.models import (
    Article,
    BlogSettings,
    Category,
    Links,
    SideBar,
    Tag,
)
from comments.models import Comment
from oauth.models import OAuthConfig, OAuthUser
from owntracks.models import OwnTrackLog
from servermanager.models import EmailSendLog, commands as ServerCommand
from djangoblog.utils import cache


SURNAMES = [
    ("zhang", "张"),
    ("li", "李"),
    ("wang", "王"),
    ("zhao", "赵"),
    ("chen", "陈"),
    ("liu", "刘"),
    ("yang", "杨"),
    ("wu", "吴"),
    ("huang", "黄"),
    ("zhou", "周"),
    ("xu", "徐"),
    ("sun", "孙"),
    ("gao", "高"),
    ("lin", "林"),
    ("he", "何"),
    ("deng", "邓"),
    ("cao", "曹"),
    ("guo", "郭"),
    ("ma", "马"),
    ("tian", "田"),
]

GIVEN_NAMES = [
    ("chenxi", "晨曦"),
    ("zihan", "子涵"),
    ("yichen", "忆辰"),
    ("siyu", "思雨"),
    ("jingwen", "婧文"),
    ("yuxuan", "宇轩"),
    ("runze", "润泽"),
    ("yutong", "语桐"),
    ("shiyu", "诗语"),
    ("mengqi", "梦琪"),
    ("jingyi", "静怡"),
    ("hongyi", "泓逸"),
    ("haoran", "浩然"),
    ("yiran", "依然"),
    ("siyuan", "思源"),
    ("yuxin", "语心"),
    ("moran", "墨然"),
    ("linna", "霖娜"),
    ("xinya", "欣雅"),
    ("hanlin", "瀚林"),
]

CATEGORY_TOPICS = {
    "技术实践": [
        "架构演进",
        "后端性能优化",
        "前端工程化",
        "微服务治理",
        "测试左移",
    ],
    "数据洞察": [
        "实时数仓",
        "指标体系",
        "可视化设计",
        "治理规范",
        "数据文化",
    ],
    "产品与协作": [
        "远程协同",
        "需求洞察",
        "跨团队合作",
        "团队搭建",
        "绩效复盘",
    ],
    "设计体验": [
        "用户旅程",
        "组件体系",
        "可访问性",
        "动效语言",
        "品牌焕新",
    ],
    "社区与文化": [
        "开源故事",
        "学习社群",
        "行业大会",
        "阅读札记",
        "创作者访谈",
    ],
    "城市出行": [
        "在地指南",
        "城市步行",
        "咖啡地图",
        "夜间骑行",
        "慢旅行",
    ],
}

TAG_POOL = [
    "开源治理",
    "工程效率",
    "云原生",
    "持续交付",
    "代码整洁",
    "服务观测",
    "容器调度",
    "后端性能",
    "数据中台",
    "指标体系",
    "用户研究",
    "交互设计",
    "体验创新",
    "远程办公",
    "团队协作",
    "敏捷实践",
    "产品迭代",
    "社区运营",
    "知识管理",
    "阅读分享",
    "旅行随笔",
    "本地生活",
    "咖啡文化",
    "夜跑记录",
    "摄影手账",
    "可持续",
    "低碳出行",
    "城市观察",
    "行业洞察",
    "数据治理",
    "安全响应",
    "测试策略",
    "设计系统",
    "品牌建设",
    "人才培养",
    "写作手记",
    "活动记录",
    "创新案例",
    "技术雷达",
]

ARTICLE_LEADS = [
    "过去十二个月，我们围绕『{topic}』做了系统化的探索。从零散尝试到形成稳态机制，这篇文章梳理了关键心路与节点。",
    "为了弄清团队在『{topic}』上遇到的真实阻碍，我们走访了十余位业务同事。记录下来的访谈笔记，改变了我们原先的假设。",
    "三年前上线的『{topic}』流程，如今迎来第三次大改版。复盘整段历程，有犀利的反馈，也有被忽略的细节。",
    "几乎每周的圆桌讨论都离不开『{topic}』。那些被推翻的方案、被坚持的原则、被复盘的教训，都整理在这份纪要中。",
    "一次茶水间聊天引发的『{topic}』专题冲刺，最终成为组织级项目。这里是含泪与含笑的完整记录。",
    "我钟爱拆解真实落地的『{topic}』案例，本篇将访谈、架构手稿与事故复盘串联起来，呈现一线视角。",
    "导师团一直想写一本可信赖的『{topic}』手册。我们花了六周时间共创，成稿的骨架与素材都在文中开放给大家。",
    "当你盯着线上曲线不知所措时，希望这份关于『{topic}』的现场记录能提供另一种决策框架。",
]

ARTICLE_BODY_BLOCKS = [
    "### 背景与动因\n我们分析了过去六个迭代的关键指标，发现瓶颈集中在响应速度与协同效率。基于这些洞察，设定了阶段性目标。",
    "### 研究方法\n研讨会采用双轨道：一条线聚焦技术验证，另一条线对接业务场景。辅以问卷调查和用户访谈，保证决策不偏离真实需求。",
    "### 实施路径\n我们将项目拆成四个里程碑：诊断、试点、推广、沉淀。每个阶段配备跨职能小组，确保信息流通顺畅。",
    "### 工具与产出\n文中附带的数据报表模板、决策树示例与演示代码，帮助团队复用这套框架。",
    "### 指标追踪\n核心指标选择了上线成功率、缺陷修复时长与团队满意度。每月公示趋势图，让变化过程可感知。",
    "### 组织协同\n最大的阻力来自角色边界。我们通过共建工作坊与角色轮值，逐步建立共享语言。",
    "### 学到的教训\n失败案例比成功案例更能说明问题。我们列出三次踩坑经历，并附上预防清单。",
    "### 影响范围\n项目让 7 个业务单元受益，专题社群成员增长 2.4 倍。更多故事等待后续分享。",
    "### 资料索引\n附上参考书目、播客与内部备忘录，方便读者延伸阅读。",
]

COMMENT_SNIPPETS = [
    "这篇文章的调研维度特别细，收益良多。",
    "指标对照表太实用了，我们也准备照着修一版。",
    "感谢分享踩坑经历，避免重蹈覆辙。",
    "对话纪要写得很真实，感受到跨团队的碰撞。",
    "想听听数据看板的搭建细节，期待后续。",
    "动因分析一针见血，已经推荐给产品同事。",
    "共建工作坊的设计非常启发，已经收藏。",
    "阅读记录部分给了我新的学习路径。",
    "从业务角度出发的复盘特别难得，点赞。",
    "请继续分享城市走访系列，很喜欢文字氛围。",
]

CITIES = [
    "北京",
    "上海",
    "深圳",
    "广州",
    "杭州",
    "成都",
    "武汉",
    "西安",
    "苏州",
    "厦门",
]

ARTICLE_TITLE_PATTERNS = [
    "{topic} 实战手记：第{number}次迭代的发现",
    "{year}年{month}月的 {topic} 复盘笔记",
    "来自{city}的一线记录：{topic} 落地细节",
    "{topic} 研讨会纪要 · 第{number}期",
    "{city}观测日记：我们如何推进 {topic}",
]


class Command(BaseCommand):
    help = "Populate the openGauss database with a large demo dataset."

    def add_arguments(self, parser):
        parser.add_argument("--users", type=int, default=200,
                            help="Number of demo users to create (excluding admin).")
        parser.add_argument("--categories", type=int, default=60,
                            help="Total number of categories to generate (including sub categories).")
        parser.add_argument("--tags", type=int, default=200,
                            help="Number of tags to generate.")
        parser.add_argument("--articles", type=int, default=800,
                            help="Number of articles to generate.")
        parser.add_argument("--comments", type=int, default=3000,
                            help="Number of comments to generate across all articles.")
        parser.add_argument("--force", action="store_true",
                            help="Clear existing blog data before seeding.")

    @transaction.atomic
    def handle(self, *args, **options):
        random.seed(2025)

        if options["force"]:
            self.stdout.write("Clearing existing dataset...")
            self._clear_existing_data()
        elif Article.objects.exists():
            self.stdout.write(self.style.WARNING(
                "Existing articles found. Re-run with --force to replace the dataset."))
            return

        self._ensure_site_configuration()
        users = self._create_users(options["users"])
        categories = self._create_categories(options["categories"])
        tags = self._create_tags(options["tags"])
        self._ensure_blog_settings()
        self._create_links()
        self._create_sidebars()
        articles = self._create_articles(options["articles"], users, categories)
        self._assign_tags_to_articles(tags, articles)
        self._create_comments(options["comments"], users, articles)
        self._create_server_commands()
        self._create_email_logs(users)
        self._create_owntracks_logs()
        self._create_oauth_configs()
        self._create_oauth_users(users)
        cache.clear()

        User = get_user_model()
        summary = {
            "用户总数": User.objects.count(),
            "文章数量": Article.objects.count(),
            "评论数量": Comment.objects.count(),
            "分类数量": len(categories),
            "标签数量": len(tags),
            "友情链接": Links.objects.count(),
            "侧栏块": SideBar.objects.count(),
            "运维指令": ServerCommand.objects.count(),
            "邮件日志": EmailSendLog.objects.count(),
            "轨迹记录": OwnTrackLog.objects.count(),
            "OAuth 用户": OAuthUser.objects.count(),
        }
        for key, value in summary.items():
            self.stdout.write(f"{key}：{value}")
        self.stdout.write(self.style.SUCCESS("中文示例数据已生成。"))

    def _clear_existing_data(self):
        Comment.objects.all().delete()
        Article.tags.through.objects.all().delete()
        Article.objects.all().delete()
        Tag.objects.all().delete()
        Category.objects.all().delete()
        Links.objects.all().delete()
        SideBar.objects.all().delete()
        BlogSettings.objects.all().delete()
        ServerCommand.objects.all().delete()
        EmailSendLog.objects.all().delete()
        OwnTrackLog.objects.all().delete()
        OAuthUser.objects.all().delete()
        OAuthConfig.objects.all().delete()
        User = get_user_model()
        User.objects.all().delete()

    def _ensure_site_configuration(self):
        Site.objects.update_or_create(
            id=getattr(settings, "SITE_ID", 1),
            defaults={
                "domain": "localhost:8000",
                "name": "知行札记",
            },
        )

    def _create_users(self, user_count):
        User = get_user_model()
        admin = User.objects.filter(username="admin").first()
        if not admin:
            admin = User.objects.create_superuser(
                username="admin",
                email="admin@example.com",
                password="Admin@2025",
                first_name="管理员",
                last_name="系统",
                nickname="站点管理员",
                source="系统初始化",
            )
        else:
            updated_fields = []
            if not admin.check_password("Admin@2025"):
                admin.set_password("Admin@2025")
                updated_fields.append("password")
            if admin.nickname != "站点管理员":
                admin.nickname = "站点管理员"
                updated_fields.append("nickname")
            if admin.source != "系统初始化":
                admin.source = "系统初始化"
                updated_fields.append("source")
            if not admin.first_name:
                admin.first_name = "管理员"
                updated_fields.append("first_name")
            if not admin.last_name:
                admin.last_name = "系统"
                updated_fields.append("last_name")
            if updated_fields:
                admin.save(update_fields=updated_fields)

        users = []
        for idx in range(user_count):
            surname_py, surname_cn = random.choice(SURNAMES)
            given_py, given_cn = random.choice(GIVEN_NAMES)
            username = f"{surname_py}{given_py}{idx + 1:04d}"
            email = f"{username}@example.cn"
            nickname = f"{surname_cn}{given_cn}"
            users.append(
                User(
                    username=username,
                    email=email,
                    password=make_password("BlogUser@2025"),
                    first_name=given_cn,
                    last_name=surname_cn,
                    nickname=nickname,
                    source="示例数据",
                    is_active=True,
                )
            )
        User.objects.bulk_create(users)
        created_users = list(User.objects.filter(source="示例数据").order_by("id"))
        return created_users

    def _create_categories(self, total_categories):
        categories = []
        self.category_topics = {}
        total_topics = len(CATEGORY_TOPICS)
        existing_names = set()

        def reserve_name(base_name, suffix_start=1):
            final_name = base_name
            suffix = suffix_start
            while len(final_name) > 30:
                keep = max(1, 30 - len(str(suffix)))
                final_name = base_name[:keep] + str(suffix)
                suffix += 1
            while final_name in existing_names:
                keep = max(1, 30 - len(str(suffix)))
                final_name = base_name[:keep] + str(suffix)
                suffix += 1
            existing_names.add(final_name)
            return final_name

        for order, (root_name, sub_topics) in enumerate(CATEGORY_TOPICS.items(), start=1):
            stored_root_name = reserve_name(root_name)
            root = Category.objects.create(
                name=stored_root_name,
                parent_category=None,
                slug=slugify(stored_root_name),
                index=total_topics - order + 1,
            )
            categories.append(root)
            self.category_topics[root.id] = root_name

            for sub_index, topic in enumerate(sub_topics, start=1):
                child_name = reserve_name(topic)
                child = Category.objects.create(
                    name=child_name,
                    parent_category=root,
                    slug=slugify(f"{root_name}-{topic}"),
                    index=len(sub_topics) - sub_index + 1,
                )
                categories.append(child)
                self.category_topics[child.id] = topic

        extra_needed = total_categories - len(categories)
        counter = 1
        while extra_needed > 0:
            desired_name = f"专题专栏·现场观察{counter}"
            stored_name = reserve_name(desired_name)
            extra = Category.objects.create(
                name=stored_name,
                parent_category=None,
                slug=slugify(stored_name),
                index=counter,
            )
            categories.append(extra)
            self.category_topics[extra.id] = desired_name
            counter += 1
            extra_needed -= 1

        return categories

    def _create_tags(self, total_tags):
        tags = []
        used_names = set()
        for idx in range(total_tags):
            base_name = TAG_POOL[idx % len(TAG_POOL)]
            if idx >= len(TAG_POOL):
                base_name = f"{base_name}{idx + 1}"
            name = base_name if base_name not in used_names else f"{base_name}-{idx + 1}"
            used_names.add(name)
            tag = Tag.objects.create(name=name, slug=slugify(name))
            tags.append(tag)
        return tags

    def _ensure_blog_settings(self):
        BlogSettings.objects.update_or_create(
            id=1,
            defaults={
                "site_name": "知行札记",
                "site_description": "聚焦技术实践、数据洞察与城市生活方式的中文博客示例。",
                "site_seo_description": "开源社区、工程效率、旅行随笔等多领域深度内容。",
                "site_keywords": "技术博客,数据分析,团队协作,城市生活,开源故事",
                "article_sub_length": 350,
                "sidebar_article_count": 15,
                "sidebar_comment_count": 10,
                "article_comment_count": 10,
                "show_google_adsense": False,
                "open_site_comment": True,
                "analytics_code": "gauss-demo-tracker",
                "comment_need_review": False,
            },
        )

    def _create_links(self):
        Links.objects.all().delete()
        link_sources = [
            ("开源之门", "https://opensource.example.cn"),
            ("工程效率手册", "https://shipbook.example.cn"),
            ("数据漫游", "https://datajourney.example.cn"),
            ("体验研究社", "https://uxlab.example.cn"),
            ("远程办公指南", "https://remotework.example.cn"),
            ("技术雷达站", "https://techradar.example.cn"),
            ("社区活动墙", "https://community.example.cn"),
            ("阅读互助会", "https://reading.example.cn"),
            ("城市慢行", "https://citywalk.example.cn"),
            ("咖啡地图", "https://coffee.example.cn"),
        ]
        links = []
        for idx in range(20):
            name, url = link_sources[idx % len(link_sources)]
            final_name = f"{name}{idx + 1}" if idx >= len(link_sources) else name
            links.append(
                Links(
                    name=final_name,
                    link=url,
                    sequence=idx + 1,
                    is_enable=True,
                )
            )
        Links.objects.bulk_create(links)

    def _create_sidebars(self):
        SideBar.objects.all().delete()
        sidebars = []
        sidebar_content = [
            "欢迎关注知行札记，每周四发布技术与生活观察。",
            "加入我们的线上读书会，共同讨论工程、商业与设计。",
            "每月一次的社区分享报名开启，点击查看议题。",
            "最新城市漫游路线已更新，周末一起探索街区。",
            "订阅邮件简报，获取幕后故事与工具清单。",
            "招募作者与翻译志愿者，欢迎私信联系。",
            "推荐使用夜间模式，边听播客边阅读。",
            "如果内容对你有帮助，记得转发给朋友。",
            "我们在 Mastodon、知乎同步更新，搜索知行札记。",
            "欢迎留言告诉我们你希望看到的话题。",
        ]
        for idx, text in enumerate(sidebar_content, start=1):
            sidebars.append(
                SideBar(
                    name=f"侧栏推荐 {idx}",
                    content=f"<p>{text}</p>",
                    sequence=idx,
                    is_enable=True,
                )
            )
        SideBar.objects.bulk_create(sidebars)

    def _create_articles(self, total_articles, users, categories):
        articles = []
        now = timezone.now()
        batch = []
        batch_size = 80
        for idx in range(total_articles):
            author = random.choice(users)
            category = random.choice(categories)
            topic_text = self.category_topics.get(category.id, category.name)
            age_days = random.randint(0, 730)
            published_at = now - timedelta(days=age_days, minutes=random.randint(0, 1440))
            title_pattern = random.choice(ARTICLE_TITLE_PATTERNS)
            base_title = title_pattern.format(
                topic=topic_text,
                number=random.randint(1, 36),
                city=random.choice(CITIES),
                year=published_at.year,
                month=published_at.month,
            )
            article_title = f"{base_title} · 档案{idx + 1:04d}"
            lead = random.choice(ARTICLE_LEADS).format(topic=topic_text)
            block_count = random.randint(4, 6)
            body_sections = random.sample(ARTICLE_BODY_BLOCKS, k=block_count)
            metrics_block = (
                "### 数据速览\n"
                f"- 关键指标完成度：{random.randint(72, 98)}%\n"
                f"- 访谈对象：{random.randint(6, 18)} 位一线伙伴\n"
                f"- 迭代周期：{random.randint(1, 4)} 周\n"
                f"- 线上复盘会：{random.randint(2, 8)} 场\n"
            )
            quote = random.choice(COMMENT_SNIPPETS)
            body = (
                f"# {article_title}\n\n"
                f"{lead}\n\n"
                + "\n\n".join(body_sections)
                + "\n\n"
                + metrics_block
                + "\n> 访谈摘录：“" + quote + "”\n"
            )
            article = Article(
                title=article_title,
                body=body,
                pub_time=published_at,
                status="p",
                comment_status=random.choice(["o", "o", "c"]),
                type="a",
                views=random.randint(120, 68000),
                author=author,
                article_order=random.randint(0, 30),
                show_toc=True,
                category=category,
            )
            article.creation_time = published_at
            article.last_modify_time = published_at + timedelta(hours=random.randint(1, 72))
            batch.append(article)
            if len(batch) >= batch_size:
                Article.objects.bulk_create(batch)
                articles.extend(batch)
                batch = []
        if batch:
            Article.objects.bulk_create(batch)
            articles.extend(batch)
        return list(Article.objects.order_by("id"))

    def _assign_tags_to_articles(self, tags, articles):
        if not tags or not articles:
            return
        through = Article.tags.through
        relations = []
        tag_ids = [tag.id for tag in tags]
        for article in articles:
            chosen_tags = random.sample(tag_ids, random.randint(3, min(6, len(tag_ids))))
            for tag_id in chosen_tags:
                relations.append(through(article_id=article.id, tag_id=tag_id))
            if len(relations) >= 20000:
                through.objects.bulk_create(relations)
                relations = []
        if relations:
            through.objects.bulk_create(relations)

    def _create_comments(self, total_comments, users, articles):
        if not users or not articles or total_comments <= 0:
            return
        created = 0
        stored_comments = {article.id: [] for article in articles}
        while created < total_comments:
            article = random.choice(articles)
            author = random.choice(users)
            comment = Comment.objects.create(
                body=f"{random.choice(COMMENT_SNIPPETS)}（#{created + 1}）",
                author=author,
                article=article,
                is_enable=random.choice([True, True, False]),
            )
            ancestors = stored_comments[article.id]
            if ancestors and random.random() < 0.35:
                comment.parent_comment = random.choice(ancestors)
                comment.save(update_fields=["parent_comment"])
            stored_comments[article.id].append(comment)
            created += 1

    def _create_server_commands(self):
        ServerCommand.objects.all().delete()
        commands = []
        templates = [
            ("巡检：数据库连接数", "python manage.py dbstats", "输出当前连接情况及慢查询统计"),
            ("巡检：缓存占用", "python manage.py show_cache", "查看 Redis 集群命中率"),
            ("维护：构建搜索索引", "python manage.py rebuild_index --noinput", "重建 Whoosh 索引，保障搜索结果"),
            ("维护：刷新静态资源", "python manage.py collectstatic --noinput", "同步最新静态文件至 CDN"),
            ("巡检：后台任务", "python manage.py celery_inspect", "检查队列堆积与任务延迟"),
            ("发布：生成版本标签", "git tag -a release-$DATE -m 'auto tag'", "记录部署版本，便于回滚"),
            ("排障：查看容器日志", "docker logs -n 200 web", "快速定位最新异常堆栈"),
            ("数据：抽样导出", "python manage.py export_insights --limit 200", "导出业务指标用于快速分析"),
            ("安全：依赖扫描", "pip-audit", "检测依赖库安全漏洞"),
            ("备份：openGauss 快照", "gs_dump -p 5432 -f backup.tar djangoblog", "拉取数据库备份，保留最近 7 天"),
        ]
        for idx in range(30):
            title, command_str, desc = templates[idx % len(templates)]
            commands.append(
                ServerCommand(
                    title=f"{title} #{idx + 1}",
                    command=command_str,
                    describe=desc,
                )
            )
        ServerCommand.objects.bulk_create(commands)

    def _create_email_logs(self, users):
        EmailSendLog.objects.all().delete()
        logs = []
        user_emails = [user.email for user in users if user.email]
        subjects = ["周报", "月度洞察", "灵感快报", "线下活动预告", "数据小抄"]
        for idx in range(1, 201):
            recipient = random.choice(user_emails) if user_emails else f"reader{idx}@example.cn"
            subject = random.choice(subjects)
            logs.append(
                EmailSendLog(
                    emailto=recipient,
                    title=f"知行札记{subject}第{idx}期",
                    content=(
                        f"本期精选了与『{random.choice(TAG_POOL)}』相关的实践案例，"
                        "并附上城市生活栏目新增的路线。欢迎回复邮件分享你的想法。"
                    ),
                    send_result=random.choice([True, False, True]),
                )
            )
        EmailSendLog.objects.bulk_create(logs)

    def _create_owntracks_logs(self):
        OwnTrackLog.objects.all().delete()
        logs = []
        base_lat, base_lon = 37.7749, -122.4194
        for idx in range(1, 501):
            logs.append(
                OwnTrackLog(
                    tid=f"citywalk-{idx:03d}",
                    lat=base_lat + random.uniform(-0.5, 0.5),
                    lon=base_lon + random.uniform(-0.5, 0.5),
                )
            )
        OwnTrackLog.objects.bulk_create(logs)

    def _create_oauth_configs(self):
        provider_defaults = {
            "weibo": "微博",
            "google": "Google",
            "github": "GitHub",
            "facebook": "Facebook",
            "qq": "QQ",
        }
        for provider, label in provider_defaults.items():
            OAuthConfig.objects.update_or_create(
                type=provider,
                defaults={
                    "appkey": f"{provider}_integration_key",
                    "appsecret": f"{provider}_integration_secret",
                    "callback_url": f"https://account.example.cn/oauth/{provider}/callback",
                    "is_enable": True,
                },
            )

    def _create_oauth_users(self, users):
        OAuthUser.objects.all().delete()
        entries = []
        providers = ["weibo", "google", "github", "facebook", "qq"]
        for idx in range(1, 201):
            author = random.choice(users) if users else None
            provider = random.choice(providers)
            entries.append(
                OAuthUser(
                    author=author,
                    openid=f"{provider}_openid_{idx:05d}",
                    nickname=f"{provider}用户{idx:04d}",
                    token=f"token-{provider}-{idx:05d}",
                    picture=f"https://cdn.example.cn/avatars/{provider}-{idx:05d}.png",
                    type=provider,
                    email=f"{provider}_user_{idx}@example.cn",
                    metadata="同步自第三方授权",
                )
            )
        OAuthUser.objects.bulk_create(entries)
